package part17;

import java.util.*;

/**
 * @author wcj
 * @Date 2021/6/1 21:31
 * @Version 1.0
 */
public class Part1715 {
}

/**
 * 一个完整的HashMap的思想，要实现entrySet()方法，其中的equals()和hashCode()
 * HashMap:用键的散列码作为数组的下标，优化它的查询速度
 * 用链表来解决冲突问题
 * 我们自己想一下它的实现过程
 * set方法：先计算hashCode得到散列码即数组下标，然后看该位置的链表，如果散列到链表的指定位置有元素了，进行冲突的解决
 * get方法：先计算hashCode得到数组下标，查询数组下标处的链表查询元素
 *
 * @param <K>
 * @param <V>
 */
class SlowMap<K, V> extends AbstractMap<K, V> {
    private List<K> keys = new ArrayList<>();
    private List<V> values = new ArrayList<>();

    @Override
    public V put(K key, V value) {
        V v = this.get(key);
        if (!keys.contains(key)) {
            keys.add(key);
            values.add(value);
        } else {
            values.set(keys.indexOf(key), value);
        }
        return v;
    }

    @Override
    public V get(Object key) {
        if (!keys.contains(key)) {
            return null;
        }
        return values.get(keys.indexOf(key));
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        Set<Map.Entry<K, V>> entries = new HashSet<>();
        Iterator<K> ki = keys.iterator();
        Iterator<V> vi = values.iterator();
        while (ki.hasNext()) {
            entries.add(new MapEntry<K, V>(ki.next(), vi.next()));
        }
        return entries;
    }

    public static void main(String[] args) {
        SlowMap<String, String> map = new SlowMap<>();
        map.putAll(Countries.capitals(3));
        System.out.println(map);
    }
}

class MapEntry<K, V> implements Map.Entry<K, V> {
    private K key;
    private V value;

    public MapEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public K getKey() {
        return key;
    }

    @Override
    public V getValue() {
        return value;
    }

    @Override
    public V setValue(V v) {
        V result = value;
        value = v;
        return result;
    }

    @Override
    public int hashCode() {
        return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof MapEntry)) {
            return false;
        }
        MapEntry obj1 = (MapEntry) obj;
        return (key == null ? obj1.getKey() == null : key.equals(obj1.getKey())) && (value == null ? obj1.getValue() == null : value.equals(obj1.getValue()));
    }

    @Override
    public String toString() {
        return key + "=" + value;
    }
}
